#pragma once

#include <metalc/mlayer/_mlayer.h>
#include <metalc/block/cobj.h>
/* 输入锁 */
#ifndef TLSF_APDS
	#define TLSF_APDS			sffwd
#endif


/* 直接定义锁和同步函数，这样就不用通过DEF定义宏函数方式传入 */
MLAYER_SYNC(tlsf, TLSF_APDS);


/* 定义输入和输出 */
OU2INFUN(cobj, tlsf_cobj)
OU2INFUN(apds, tlsf_apds)


/* 使用宏方式填入有其好处，但是仅在一个.c中生效 */

/* 这些玩意应该通过宏输入的方式配置 */
typedef const struct tlsf_conf {
	const hword_t fli;
	const hword_t sli;
	const hword_t max_sli;
	const hword_t toffst;
	const size_t align_tlsf;
	const size_t small_size;
	const hword_t fli_offst;
	const hword_t real_fli;
	const size_t tlsf_req_size;
} tlsf_conf_t;

/* 输入最小大小，最大大小和sli来配置tlsf */
#define CONF_TLSF(confname, TLSF_MINBIT, TLSF_MAXBIT, TLSF_REQ_SIZE, SLI) \
static const tlsf_conf_t confname = { \
	.fli = TLSF_MAXBIT,\
	.sli = SLI,\
	.max_sli = (1 << SLI),\
	.toffst = TLSF_MINBIT,\
	.align_tlsf = 1UL << TLSF_MINBIT,\
	.small_size = 1UL << (SLI + TLSF_MINBIT),\
	.fli_offst = SLI + TLSF_MINBIT,\
	.real_fli = TLSF_MAXBIT - SLI - TLSF_MINBIT,\
	.tlsf_req_size = TLSF_REQ_SIZE\
	};

/* 整个数据结构都需要在后续定义 */
typedef word_t tlsf_flmap_t;
typedef hword_t tlsf_slmap_t;
typedef struct tlsf_obj{
	/* 锁 */
	tlsf_apds_t apds_obj;

	
	/* 边界节点 */
	void *sentry;
	// page_heap
	// word_t total_size;
	word_t total_free;
	
	/* 空节点 */
	dlist_t null_node;

	tlsf_flmap_t fl_map;
	tlsf_slmap_t sl_map[];
} tlsf_obj_t;

/* 通过偏移量计算 */
#define TLSF_GET_FREELISTS(tlsf_obj, real_fli)		(dlist_t **)((void *)(tlsf_obj) + sizeof(tlsf_obj_t) + align_up(sizeof(tlsf_slmap_t) * real_fli, sizeof(word_t)))

SAI size_t __tlsf_totalsize(tlsf_conf_t *conf){
	/* tlsf_obj_t + REAL_FLI个map + REAL_FLI * REALFLI个freelist */
	return sizeof(tlsf_obj_t) + align_up(sizeof(tlsf_slmap_t) * conf->real_fli, sizeof(word_t)) + sizeof(dlist_t *) * conf->max_sli * conf->real_fli;
}

/* 根据const 初始化tlsf结构体 */
SAI NO_UNROLL tlsf_obj_t *__tlsf_init(void *mem, size_t size, tlsf_conf_t *conf){
	size_t total_size = __tlsf_totalsize(conf);
	ASSERT(size >= total_size);
	ASSERT(mem);
	tlsf_obj_t *tlsf = (tlsf_obj_t *)mem;
	dlist_t **pflist = TLSF_GET_FREELISTS(tlsf, conf->real_fli);
	/* 初始化锁 */
	MLAYER_APDS_INIT(TLSF_APDS, &tlsf->apds_obj, sizeof(tlsf->apds_obj));
	// tlsf->total_size = 0;
	tlsf->total_free = 0;
	tlsf->fl_map = 0;
	tlsf->sentry = NULL;
	dlist_init(&tlsf->null_node);

	// INFO("[tlsf] init [%p - %p], real fli %x, max_sli %x, flists %p\n", mem, mem + total_size, conf->real_fli, conf->max_sli, flist);
	/* 初始化各map和 freelists */
	for (hword_t i = 0; i < conf->real_fli; i++)
	{
		tlsf->sl_map[i] = 0;
		for (hword_t j = 0; j < conf->max_sli; j++)
		{
			// INFO("[tlsf] init flists [%x, %x] %p\n", i, j, &flist[i * conf->max_sli + j]);
			pflist[i * conf->max_sli + j] = &tlsf->null_node;
		}
	}
	return tlsf;
}


/* 辅助函数 */
SAI void _tlsf_mapping_insert(size_t size, hword_t *fl, hword_t *sl, tlsf_conf_t *conf)
{
	hword_t fli, sli;
	if (size < conf->small_size)
	{
		fli = 0;
		sli = size >> conf->toffst;
	}
	else
	{
		fli = __FLSG(size) - 1;
		sli = (size >> (fli - conf->sli)) ^ (1UL << conf->sli);
		fli -= conf->fli_offst - 1;
	}
	*fl = fli;
	*sl = sli;
}

SAI void _tlsf_mapping_search(size_t size, hword_t *fli, hword_t *sli, tlsf_conf_t *conf)
{
	if (size >= conf->small_size)
	{
		word_t round = (1UL << (__FLSG(size) - conf->sli - 1)) - 1;
		size += round;
	}
	_tlsf_mapping_insert(size, fli, sli, conf);
}

SAI uvoid *_tlsf_find_suitable_block(tlsf_obj_t *l, hword_t *fl, hword_t *sl, tlsf_conf_t *conf)
{
	hword_t fli = *fl;
	hword_t sli = *sl;

	hword_t sl_map = l->sl_map[fli] & ((~0U) << sli);
	if (!sl_map)
	{
		word_t fl_map = l->fl_map & ((~0U) << (fli + 1));
		if (!fl_map)
		{
			return NULL;
		}
		fli = __FFSG(fl_map) - 1;
		*fl = fli;
		sl_map = l->sl_map[fli];
	}
	sli = __FFSG(sl_map) - 1;
	*sl = sli;
	
	dlist_t **flists = TLSF_GET_FREELISTS(l, conf->real_fli);
	return flists[fli * conf->max_sli + sli];
}

// 删除节点,如果是头则修改bitmap
SAI void _tlsf_remove_free_block(tlsf_obj_t *l, dlist_t *blk, size_t blk_availsz, hword_t fl, hword_t sl, tlsf_conf_t *conf)
{
	// 删除
	dlist_t *prev_node = blk->prev;
	dlist_t *next_node = blk->next;
	dlist_t **flists = TLSF_GET_FREELISTS(l, conf->real_fli);
	dlist_t *exact_flist = flists[fl * conf->max_sli + sl];
	INFO("[tlsf] remove block %p, avail_size %lx, from fl %x, sl %x, flist %p\n", blk, blk_availsz, fl, sl, exact_flist);
	dlist_del(prev_node, next_node);
	
	if (exact_flist == blk)
	{
		flists[fl * conf->max_sli + sl] = next_node;

		if (next_node == &l->null_node){
			/* 清除bitmap */
			l->sl_map[fl] &= ~(1UL << sl);
			if (!l->sl_map[fl])
			{
				l->fl_map &= ~(1UL << fl);
			}
		}
		INFO("[tlsf] clean fl %x sl %x\n", fl, sl);
	}
	// ASSERT(l->total_free >= cobj_calc_availsize(blk_availsz));
	l->total_free -= blk_availsz;
}
// 插入过程伴随着bitmap的修改
SAI void _tlsf_add_free_block(tlsf_obj_t *l, dlist_t *blk, hword_t fl, hword_t sl, size_t blk_availsz, tlsf_conf_t *conf)
{
	// 判断队列
	dlist_t **flists = TLSF_GET_FREELISTS(l, conf->real_fli);
	dlist_t *cur = flists[fl * conf->max_sli + sl];
	blk->next = cur;
	blk->prev = &l->null_node;
	cur->prev = blk;

	flists[fl * conf->max_sli + sl] = blk;

	/* 修改map */
	l->fl_map |= (1UL << fl);
	l->sl_map[fl] |= (1UL << sl);

	/* 增加free size */
	l->total_free += blk_availsz;
}

SIN void *_tlsf_split_insert(tlsf_obj_t *l, void *mem, size_t size, size_t rqsz, size_t real_size, tlsf_conf_t *conf, INFUN(tlsf_cobj, cobj)){
	hword_t fl, sl;
	/* 前向分割 */
	
	size_t usedblk_size = rqsz + cobj->mocupysz();
	size_t freeblk_size = size - usedblk_size;
	/* 如果需要对齐则应该切后半部分 */

	/* 支持对齐部分 */
	
	if (UNLIKELY(rqsz > real_size)){
		size_t align = rqsz - real_size;
		/* 需要对齐用户指针 */
		uvoid *fst_blk = cobj->ptr2uptr(mem);
		/* 对齐 */
		uvoid *alg_uptr = (uvoid *)align_up((paddr_t)mem + cobj->mocupysz() + sizeof(dlist_t) + cobj->mocupysz(), align);
		void *alg_ptr = cobj->uptr2ptr(alg_uptr);
		size_t offst_alg = (paddr_t)alg_ptr - (paddr_t)mem;
		// ASSERT(offst_alg <= size - usedblk_size);
		/* 切割 */
		if (offst_alg >= cobj->mocupysz() + sizeof(dlist_t)){
			/* 插回去 [mem, mem + offst_alg] */
			/* 切割 */
			cobj->split(mem, size, offst_alg, TRUE);
			INFO("[tlsf] split aligned [%p, %p] to [%p, %p] and [%p, %p]\n", mem, mem+size, mem, mem+offst_alg, mem+offst_alg, mem+size);
			size_t header_blksz = offst_alg - cobj->mocupysz();

			// ASSERT(offst_alg >= cobj->mocupysz() + sizeof(dlist_t));
			
		
			_tlsf_mapping_insert(header_blksz, &fl, &sl, conf);
			_tlsf_add_free_block(l, (dlist_t *)fst_blk, fl, sl, header_blksz, conf);
		}
		else{
			INFO("[tlsf] offst alg is %lx\n", offst_alg);
			/* 头部必须大于32? 不然有可能存在0块(其实可以接受，不插入即可，到时候仍然可以合并)*/
			// ASSERT(offst_alg >= cobj->mocupysz());
			ASSERT(offst_alg == 0);
			/* 切割 */
			// cobj->split(mem, size, offst_alg, TRUE);
		}
		size_t nsize = size - offst_alg;
		// ASSERT(nsize >= usedblk_size);
		/* 分裂出 [alg_ptr, alg_ptr + (size - offst_alg)] */
		/* 尾递归 */
		// void *ret = _tlsf_split_insert(l, alg_ptr, nsize, real_size, real_size, conf, cobj);
		// dbg_printf("[tlsf] aligned %lx, return %p, uptr %p, size %lx\n", align, ret, cobj->ptr2uptr(ret), real_size);
		// ASSERT(is_ptr_aligned(cobj->ptr2uptr(ret), align));
		// ASSERT(cobj->ptr_getsize(ret) >= real_size + cobj->mocupysz());
		// return ret;
		return _tlsf_split_insert(l, alg_ptr, nsize, real_size, real_size, conf, cobj);
	}

	/* 不满足拆分条件，必须在判断对齐后使用 */
	if (freeblk_size < cobj->mocupysz() + sizeof(dlist_t)) {
		/* 直接返回 */
		INFO("[tlsf] set [%p, %p] used\n", mem, mem+size);
		cobj->set_cobj(mem, size, 1);
		return mem;
	}
	/* 取前半部分 */
	void *other_half = cobj->split(mem, size, usedblk_size, TRUE);
	/* 取后半部分 */
	// void *other_half = mem;
	// mem = cobj->split(mem, size, freeblk_size, TRUE);



	INFO("[tlsf] try split mem %p, size %lx for reqsize %lx to [%p] size %lx - [%p] size %lx\n", mem, size, rqsz, mem, rqsz + cobj->mocupysz(), other_half, freeblk_size);
	if (other_half){
		/* 切割完后插入 */
		size_t newblk_availsz = freeblk_size - cobj->mocupysz();
		// ASSERT(freeblk_size >= cobj->mocupysz() + sizeof(dlist_t));
		_tlsf_mapping_insert(newblk_availsz, &fl, &sl, conf);
		_tlsf_add_free_block(l, (dlist_t *)cobj->ptr2uptr(other_half), fl, sl, newblk_availsz, conf);
	}
	/* 设置使用 */
	INFO("[tlsf] set [%p, %p] used\n", mem, mem+usedblk_size);
	cobj->set_cobj(mem, usedblk_size, 1);
	return mem;
}
SAI dlist_t *_tlsf_try_merge_prev(tlsf_obj_t *l, dlist_t *blk, size_t *availsize, tlsf_conf_t *conf, INFUN(tlsf_cobj, cobj))
{
	/* 尝试合并前者 */
	hword_t fl, sl;
	void *ptr = cobj->uptr2ptr((uvoid *)blk);
	size_t ptr_size = *availsize + cobj->mocupysz();
	/* TODO: sz == 0? */
	void *prev_ptr = cobj->get_prev(ptr, ptr_size);
	if (!prev_ptr) return blk;
	dlist_t *prev_node = (dlist_t *)cobj->ptr2uptr(prev_ptr);
	size_t prev_size = cobj->ptr_getsize(prev_ptr);
	// _tlsf_mapping_insert(prev_size - cobj->mocupysz(), &fl, &sl, conf);
	INFO("[tlsf] try merge prev, prev_ptr %p, prev_size %lx, cur %p\n", prev_ptr, prev_size, ptr);
	/* 确保邻接 */
	ASSERT(prev_ptr + prev_size == ptr);
	size_t new_size = cobj->merge_next(prev_ptr, prev_size);
	if (new_size != prev_size){
		/* 合并成功 */
		ASSERT(new_size == prev_size + ptr_size);
		_tlsf_mapping_insert(prev_size - cobj->mocupysz(), &fl, &sl, conf);
		INFO("[tlsf] merged succ %p, size %lx\n", prev_ptr, new_size);
		_tlsf_remove_free_block(l, prev_node, prev_size - cobj->mocupysz(), fl, sl, conf);
		/* 返回prev_node */
		blk = prev_node;
		*availsize = new_size - cobj->mocupysz();
	}

	return blk;

}

SAI dlist_t *_tlsf_try_merge_next(tlsf_obj_t *l, dlist_t *blk, size_t *availsize, tlsf_conf_t *conf, INFUN(tlsf_cobj, cobj))
{
	/* 尝试合并下一个 */
	hword_t fl, sl;
	void *ptr = cobj->uptr2ptr((uvoid *)blk);
	size_t ptr_size = *availsize + cobj->mocupysz();
	
	void *next = ptr + ptr_size;
	dlist_t *next_node = (dlist_t *)cobj->ptr2uptr(next);
	size_t next_size = cobj->ptr_getsize(next);
	// /* 提前发射隐藏延迟? */
	// _tlsf_mapping_insert(next_size - cobj->mocupysz(), &fl, &sl, conf);
	
	size_t new_sz = cobj->merge_next(ptr, ptr_size);
	INFO("[tlsf] try merge next %p, next size %lx, state %x\n", next, next_size, new_sz != ptr_size);
	if (new_sz != ptr_size){
		_tlsf_mapping_insert(next_size - cobj->mocupysz(), &fl, &sl, conf);
		/* 找到remove next指针 */
		INFO("[tlsf] merged succ %p, size %lx\n", ptr, new_sz - cobj->mocupysz());
		
		_tlsf_remove_free_block(l, next_node, next_size - cobj->mocupysz(), fl, sl, conf);
		*availsize = new_sz - cobj->mocupysz();
	}

	return blk;
}

/* 定义临界区函数 */
STA_INFUN(tlsf_critsec)
uvoid*	(* const tlsf_alloc)(tlsf_obj_t *l, size_t req_alsz, hword_t fl, hword_t sl, size_t req_size);
void	(* const tlsf_free)(tlsf_obj_t *l, void *mem, size_t sz);
END_INFUN(tlsf_critsec)

SAI uvoid* __tlsf_alloc(tlsf_obj_t *l, size_t req_alsz, hword_t fl, hword_t sl, size_t req_size, const mlfunc_t * cont, tlsf_conf_t *conf, INFUN(tlsf_cobj, cobj)){
	INFO("[tlsf] try alloc %lx, fl %x, sl %x...\n", req_alsz, fl, sl);
	uvoid *ret = _tlsf_find_suitable_block(l, &fl, &sl, conf);


	if (LIKELY(ret)){
		void *ret_ptr = cobj->uptr2ptr(ret);
		size_t ret_size = cobj->ptr_getsize(ret_ptr);
		/* 申请到进行切割 */
		_tlsf_remove_free_block(l, (dlist_t *)ret, ret_size - cobj->mocupysz(), fl, sl, conf);
		/* 分裂并设置使用 */
		ret_ptr = _tlsf_split_insert(l, ret_ptr, ret_size, req_alsz, req_size, conf, cobj);
		// ret_size = req_alsz + cobj->mocupysz();
		ret = cobj->ptr2uptr(ret_ptr);
		INFO("[tlsf] " PRIN_RED() "alloc" PRIN_DFT() " %p, size %lx flag set used\n", ret_ptr, cobj->ptr_getsize(ret_ptr));
		// cobj->set_cobj(ret_ptr, ret_size, 1);
		ASSERT(ret_ptr);
	}
	else{
		/* 向上请求 */
		void *ret_ptr;
		mreq_t req;
		size_t req_size = (req_alsz + cobj->mocupysz()) < conf->tlsf_req_size ? 
				conf->tlsf_req_size : req_alsz + cobj->mocupysz();
		mreq_setalloc(&req, req_size, 0);
		/* 这个请求怎么消除? */
		cont->lalloc(&req);
		ret_ptr = req.ptr;
		INFO("[tlsf] oom, alloc %p, size %lx from upper layer\n", ret_ptr, req_size);
		
		/* 制造一个 guard */

		/* sentry和新地址邻接，合并guard */
		if (l->sentry + cobj->mocupysz() == ret_ptr){
			INFO("[tlsf] sentry boundary merging %p\n", l->sentry);
			req_size += cobj->mocupysz();
			ret_ptr = l->sentry;
		}
		/* 标记大小 */
		cobj->set_cobj(ret_ptr, req_size, 0);
		l->sentry = cobj->split(ret_ptr, req_size, req_size - cobj->mocupysz(), FALSE);
		cobj->set_cobj(l->sentry, 0, 1);
		INFO("[tlsf] generate boundary guard %p, and init block %p, size %lx\n", l->sentry, ret_ptr, cobj->ptr_getsize(ret_ptr));
		req_size -= cobj->mocupysz();
		if (ret_ptr){
			/* 切割 */
			ret_ptr = _tlsf_split_insert(l, ret_ptr, req_size, req_alsz, req_size, conf, cobj);

			ret = cobj->ptr2uptr(ret_ptr);
			INFO("[tlsf] upper alloc %p, size %lx flag set used\n", ret_ptr, req_alsz + cobj->mocupysz());
			// cobj->set_cobj(ret_ptr, req_alsz + cobj->mocupysz(), 1);
			ASSERT(ret_ptr);
		}
	}
	return ret;
}
SAI void __tlsf_free(tlsf_obj_t *l, void *mem, size_t sz, tlsf_conf_t *conf, INFUN(tlsf_cobj, cobj)){
	/* 设置成free */
	INFO("[tlsf] try free %p, sz %lx...\n", mem, sz);
	uvoid *uptr = cobj->set_cobj(mem, sz, 0);
	
	size_t availsz = sz - cobj->mocupysz();
	dlist_t *node = (dlist_t *)uptr;
	
	
	node = _tlsf_try_merge_next(l, node, &availsz, conf, cobj);
	INFO("[tlsf] %p after merge next, sz %lx\n", node, availsz);
	node = _tlsf_try_merge_prev(l, node, &availsz, conf, cobj);
	INFO("[tlsf] %p after merge prev, sz %lx\n", node, availsz);

	hword_t fl, sl;
	_tlsf_mapping_insert(availsz, &fl, &sl, conf);
	_tlsf_add_free_block(l, node, fl, sl, availsz, conf);
	INFO("[tlsf] " PRIN_YELLOW() "freed" PRIN_DFT()" %p, sz %lx...\n", mem, sz);
}
/* 定义临界区 */
#define DEF_TLSF_CRTISEC(name, cobj_comp, apds_comp, pconf)	\
static const mlfunc_t name##_mlfunc;\
SAI uvoid* name##_tlsf_alloc__(tlsf_obj_t *l, size_t req_alsz, hword_t fl, hword_t sl, size_t req_size){\
	return __tlsf_alloc(l, req_alsz, fl, sl, req_size, &name##_mlfunc, pconf, OUFUN_OF(cobj_comp));\
}\
SAI void name##_tlsf_free__(tlsf_obj_t *l, void *mem, size_t sz){\
	__tlsf_free(l, mem, sz, pconf, OUFUN_OF(cobj_comp));\
}\
static apdsret_t name##_tlsf_alloc_crit(APDSFUNC_ARGLIST){\
	tlsf_obj_t *l = (tlsf_obj_t *)arg0;\
	size_t req_alsz = (size_t)arg1;\
	hword_t fl = (hword_t)word_high(arg2);\
	hword_t sl = (hword_t)word_low(arg2);\
	size_t req_size = (size_t)arg3;\
	return (apdsret_t)name##_tlsf_alloc__(l, req_alsz, fl, sl, req_size);\
}\
static apdsret_t name##_tlsf_free_crit(APDSFUNC_ARGLIST){\
	tlsf_obj_t *l = (tlsf_obj_t *)arg0;\
	void *mem = (void *)arg1;\
	size_t sz = (size_t)arg2;\
	PARAM_USED(arg3);\
	name##_tlsf_free__(l, mem, sz);\
	return (apdsret_t)NULL_PTR;\
}\
SAI uvoid *name##_tlsf_alloc(tlsf_obj_t *l, size_t req_alsz, hword_t fl, hword_t sl, size_t req_size){\
	APDS_ARGS(apdsarg, l, req_alsz, new_word(fl, sl), req_size);\
	return (uvoid *) MLAYER_APDS_SYNC(apds_comp, &l->apds_obj, name##_tlsf_alloc_crit, apdsarg);\
}\
SAI void name##_tlsf_free(tlsf_obj_t *l, void *mem, size_t sz){\
	APDS_ARGS(apdsarg, l, mem, sz);\
	MLAYER_APDS_SYNC(apds_comp, &l->apds_obj, name##_tlsf_free_crit, apdsarg);\
}\
NEW_INFUN(tlsf_critsec, name##_critsec, name##_tlsf_alloc, name##_tlsf_free)



SAI void _tlsf_pinit(const mlfunc_t * cont){
	PARAM_USED(cont);
	INFO("tlsf pinit\n");
}

SAI void _tlsf_tinit(const mlfunc_t * cont, tlsf_obj_t *tlsf, bool_t thread_local){
	if (thread_local) {
		mtls_t *tls = mtls_get();
		if (!tls->objs[cont->lidx])
			tls->objs[cont->lidx] = tlsf;
	}
	INFO("tlsf tinit\n");
}

// static pthread_mutex_t test_lock;
/* 如果考虑对齐的问题??增加一套对齐分配接口? */
SAI void *_tlsf_alloc(mreq_t *req, const mlfunc_t * cont, tlsf_obj_t *tlsf, tlsf_conf_t *conf, INFUN(tlsf_cobj, cobj), INFUN(tlsf_critsec, crit)){
	/* 对齐请求大小 */
	size_t req_size = req->size;
	if (MLAYER_INVALID_REQSZ(cont, req_size)) return cont->lalloc(req);
	ASSERT(tlsf);
	
	mtls_by_req(req);
	/* 计算fli和sli(避免在临界区中计算) */
	hword_t fli, sli;
	/* 先对齐 */
	size_t size = align_up(req_size, conf->align_tlsf);
	size_t algn_sz = size;
	/* 检查对齐 */
	if (UNLIKELY(req->align != 0)){
		/* 非对齐 */
		/* 先申请，再强行对齐 */
		
		if (req->align > sizeof(dword_t))
			algn_sz += req->align;
		
		INFO("[tlsf] req size %lx, align %lx, algn_sz %lx\n", size, req->align, algn_sz);
	}

	_tlsf_mapping_search(algn_sz, &fli, &sli, conf);

	/* 尝试加锁分配 */
	uvoid *uptr = crit->tlsf_alloc(tlsf, algn_sz, fli, sli, size);
	req->ptr = cobj->uptr2ptr(uptr);

	/* 判断是否对齐 */
/* 	if (req->align != 0){
		if (!is_ptr_aligned(uptr, req->align)){
			dbg_printf("[tlsf] error return %p, sz %lx, align %lx, blk size %lx\n", uptr, req->size, req->align, cobj->ptr_getsize(req->ptr));
		}
		INFO("[tlsf] return %p, sz %lx, align %lx\n", uptr, req->size, req->align);
		ASSERT(is_ptr_aligned(uptr, req->align));
	} */
	// ASSERT(cobj->ptr_getsize(req->ptr) >= size + cobj->mocupysz());
	/* 释放锁 */
	return uptr;
}

SAI bool_t _tlsf_free(mreq_t *req, const mlfunc_t * cont, tlsf_obj_t *tlsf, INFUN(tlsf_cobj, cobj), INFUN(tlsf_critsec, crit)){
	size_t req_size = req->size;
	if (MLAYER_INVALID_REQSZ(cont, req_size)) return cont->lfree(req);
	/* 尝试获得并且确保初始化, 放在free进行判断可以减少malloc的分支数量 */
	mtls_by_req(req);
	

	/* 加锁释放 */
	void *ptr = cobj->uptr2ptr(req->ptr);
	
	/* 清除标记: 应该在锁中完成 */
	/* cobj->set_cobj(ptr, req->size, 0); */

	crit->tlsf_free(tlsf, ptr, req->size);
	/* 释放锁 */
	return TRUE;
}

SAI size_t _tlsf_sizeof(mreq_t *req, const mlfunc_t * cont, INFUN(tlsf_cobj, cobj)){
	/* 确保分支判断被优化 */
	ASSERT(MLAYER_IS_LASTLAYER(cont));

	if (MLAYER_IS_LASTLAYER(cont) || !is_ptr_aligned(req->ptr, cont->lmaxsize)){
		/* 指针非对齐才是它管理的 */
		uvoid *uptr = req->ptr;
		void *ptr = cobj->uptr2ptr(uptr);
		size_t sz = cobj->ptr_getsize(ptr);
		// req->ptr = ptr;
		req->size = sz;
		/* 以下返回真实大小 */
		INFO("[tlsf] sizeof %p, size %lx, usize %lx\n", ptr, sz, sz - cobj->mocupysz());
		
		ASSERT(sz != 0);
		return sz - cobj->mocupysz();
	}
	return cont->lsizeof(req);
}

/* buddy 
	- ptlsf : 外部状态变量指针
	单线程
*/
#define DEF_TLSF_MLAYER(name, ptlsf, minbit, maxbit, tlsf_req_sz, sli, oalloc) \
DEF_MLAYER_BASIC(name, BIT_OVF(maxbit), 0)\
CONF_TLSF(name##_conf, minbit, maxbit, tlsf_req_sz, sli)\
DEF_TLSF_CRTISEC(name, cobjin, TLSF_APDS, &name##_conf)\
/* 必须初始化外部pmap */\
SAI void name##_pinit(const mlfunc_t * cont){\
	_tlsf_pinit(cont); }\
SAI void name##_tinit(const mlfunc_t * cont){\
	/* 无论是单一堆还是分离堆，在线程开始应该初始化 */\
	if (ptlsf == NULL_PTR){\
		size_t size = __tlsf_totalsize(&name##_conf);\
		void *tlsfmem = oalloc(size); \
		ptlsf = __tlsf_init(tlsfmem, size, &name##_conf);\
	}\
	return _tlsf_tinit(cont, ptlsf, 0); }\
SAI void *name##_alloc(mreq_t *req, const mlfunc_t * cont){\
	return _tlsf_alloc(req, cont, ptlsf, &name##_conf, OUFUN_OF(cobjin), INFUN_OF(name##_critsec));\
}\
SAI bool_t name##_free(mreq_t *req, const mlfunc_t * cont){\
	return _tlsf_free(req, cont, ptlsf,  OUFUN_OF(cobjin), INFUN_OF(name##_critsec));\
}\
SAI size_t name##_sizeof(mreq_t *req, const mlfunc_t * cont){\
	return _tlsf_sizeof(req, cont, OUFUN_OF(cobjin));\
}

